﻿using DnD.Common;
using DnD.Model;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Info;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data.Linq;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;

namespace DnD.ViewModels
{
    class GameViewModel : INotifyPropertyChanged
    {

        public ObservableCollection<Card> Cards { get; set; }
        public ObservableCollection<DnDAction> Actions { get; set; }
        public DelegateCommand NextCardCommand { get; set; }


        private Card _selectedCard;
        private Storyboard _cardInStoryboard;
        private Storyboard _cardOutStoryboard;
        private PhoneApplicationPage _view;
        private double _cardItemPosition;
        private string _deviceId;
        private bool gestureEnabled;
        private HashSet<int> usedCards;
        private Random rnd;

        public Card SelectedCard
        {
            get { return _selectedCard; }
            set
            {
                _selectedCard = value;
                OnPropertyChanged();
               
            }
        }

        public Storyboard CardInStoryboard
        {
            get { return _cardInStoryboard; }
            set
            {
                _cardInStoryboard = value;
                OnPropertyChanged();

                _cardInStoryboard.Completed += _cardInStoryboard_Completed;
                _cardInStoryboard.Begin();

            }
        }

        

        public Storyboard CardOutStoryboard
        {
            get { return _cardOutStoryboard; }
            set
            {
                _cardOutStoryboard = value;
                OnPropertyChanged();
                _cardOutStoryboard.Completed +=_cardOutStoryboard_Completed;

            }
        }

        public double CardItemPosition
        {
            get { return _cardItemPosition; }
            set
            {
                _cardItemPosition = value;
                OnPropertyChanged();
                if (value <= -25 && gestureEnabled==true)
                {
                    gestureEnabled = false;
                    _cardOutStoryboard.Begin();
                }

            }
        }

        public String DeviceId
        {
            get { return _deviceId; }
            set
            {
                _deviceId = value;
                OnPropertyChanged();

            }
        }

        private void _cardOutStoryboard_Completed(object sender, EventArgs e)
        {

            int cardIndex = ((int)(rnd.NextDouble() * 100)) % Cards.Count;
            while (usedCards.Contains(cardIndex))
            {
                cardIndex = ((int)(rnd.NextDouble() * 100)) % Cards.Count;
            }
            
            SelectedCard = Cards[cardIndex];
            usedCards.Add(cardIndex);
            if (usedCards.Count >= Cards.Count)
            {
                usedCards.Clear();
            }

            Actions.Clear();
            foreach (CardAction action in SelectedCard.Actions)
            {
                Actions.Add(action.ActionRef);
            }

            App.appStateMap["gameCardIndex"] = cardIndex;
            App.appStateMap["usedCards"] = usedCards.ToArray();

            _cardInStoryboard.Begin();
        }

        void _cardInStoryboard_Completed(object sender, EventArgs e)
        {
            gestureEnabled = true;
        }

        public void CardItem_ManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
        {

        }

        public void CardItem_ManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
        {
            CardItemPosition = CardItemPosition + e.DeltaManipulation.Translation.X;
        }

       

        public GameViewModel(int deckID, PhoneApplicationPage view)
        {
            _view = view;


            var options = new DataLoadOptions();

            options.LoadWith<Card>(c => c.Actions);
            options.LoadWith<CardAction>(ca => ca.ActionRef);

            using (var context = new DnDDataContext(DnDDataContext.DbConnectionString))
            {
                context.LoadOptions = options;

                var cards = from c in context.GameItems from cd in context.CardDecks  
                            where c.Id == cd.CardID && cd.DeckID==deckID  select c;
                Cards = new ObservableCollection<Card>(cards.OfType<Card>());


            }
            Actions = new ObservableCollection<DnDAction>();
            NextCardCommand = new DelegateCommand(showNextCard, name => true);
            

            CardItemPosition = -500;
            gestureEnabled = false;
            usedCards = new HashSet<int>();
            rnd = new Random(4367353);

            if (App.appStateMap.ContainsKey("gameCardIndex") && App.appStateMap.ContainsKey("usedCards") && App.appStateMap["gameCardIndex"] != null && App.appStateMap["usedCards"] != null)
            {
                SelectedCard = Cards[(int)App.appStateMap["gameCardIndex"]];


                foreach(int cardIndex in (int[])App.appStateMap["usedCards"])
                {
                    usedCards.Add(cardIndex);
                }

                Actions.Clear();
                foreach (CardAction action in SelectedCard.Actions)
                {
                    Actions.Add(action.ActionRef);
                }

            }
            else
            {
                
                int cardIndex = ((int)(rnd.NextDouble() * 100)) % Cards.Count;
                SelectedCard = Cards[cardIndex];
                usedCards.Add(cardIndex);

                Actions.Clear();
                foreach (CardAction action in SelectedCard.Actions)
                {
                    
                    Actions.Add(action.ActionRef);
                }

            }
           

            DeviceId = Convert.ToBase64String((byte[])DeviceExtendedProperties.GetValue("DeviceUniqueId"));
           
           

        }

        private void showNextCard(object name)
        {
            gestureEnabled = false;
            _cardOutStoryboard.Begin();
            
        }

        public void clearAppState()
        {
            App.appStateMap["gameCardIndex"] = null;
            App.appStateMap["usedCards"] = null;
        }


       

        public string BackGroundImageSource
        {
            get
            {
                if ((Visibility)App.Current.Resources["PhoneDarkThemeVisibility"]
                  == Visibility.Visible)
                {
                    return "/Assets/Pictures/dragonfire.jpg";

                }
                else
                {
                    return "/Assets/Pictures/dragonfire_negative.jpg";

                }
            }
            private set { }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
